use std::str::FromStr;
use crate::parser::{ExpressionParser, Rule, Token};
use pest::iterators::Pair;

impl ExpressionParser {
    pub fn get_name_and_value(record: Pair<Rule>) -> (String, String) {
        if let Some(inner) = record.into_inner().next() {
            let rule = inner.as_rule();
            let rule_name = format!("{:?}", rule);

            return if rule_name == "OCT_INTEGER" {
                ("INTEGER_CONST".to_string(), i32::from_str_radix(inner.as_str().trim_start_matches('0'), 8).unwrap().to_string())
            } else if rule_name == "HEX_INTEGER" {
                ("INTEGER_CONST".to_string(), i32::from_str_radix(inner.as_str().trim_start_matches("0x"), 16).unwrap().to_string())
            } else if rule_name == "DEX_INTEGER" {
                ("INTEGER_CONST".to_string(), inner.as_str().to_string())
            } else if rule_name == "ZERO" {
                ("INTEGER_CONST".to_string(), "0".to_string())
            } else if is_uppercase(&rule_name) {
                (rule_name, inner.as_str().to_string())
            } else {
                Self::get_name_and_value(inner)
            }
        }

        ("".to_string(), "".to_string())
    }

    pub fn get_token_name(record: Pair<Rule>) -> Option<Token> {
        if let Some(inner) = record.into_inner().next() {
            let rule = inner.as_rule();

            match rule {
                Rule::CONST => { return Some(Token::Const) }
                Rule::INT => { return Some(Token::Int) }
                Rule::VOID => { return Some(Token::Void) }
                Rule::IF => { return Some(Token::If) }
                Rule::ELSE => { return Some(Token::Else) }
                Rule::WHILE => { return Some(Token::While) }
                Rule::BREAK => { return Some(Token::Break) }
                Rule::CONTINUE => { return Some(Token::Continue) }
                Rule::RETURN => { return Some(Token::Return) }
                Rule::PLUS => { return Some(Token::Plus) }
                Rule::MINUS => { return Some(Token::Minus) }
                Rule::MUL => { return Some(Token::Mul) }
                Rule::DIV => { return Some(Token::Div) }
                Rule::MOD => { return Some(Token::Mod) }
                Rule::ASSIGN => { return Some(Token::Assign) }
                Rule::EQ => { return Some(Token::Eq) }
                Rule::NEQ => { return Some(Token::Neq) }
                Rule::LT => { return Some(Token::Lt) }
                Rule::GT => { return Some(Token::Gt) }
                Rule::LE => { return Some(Token::Le) }
                Rule::GE => { return Some(Token::Ge) }
                Rule::NOT => { return Some(Token::Not) }
                Rule::AND => { return Some(Token::And) }
                Rule::OR => { return Some(Token::Or) }
                Rule::L_PAREN => { return Some(Token::LParen) }
                Rule::R_PAREN => { return Some(Token::RParen) }
                Rule::L_BRACE => { return Some(Token::LBrace) }
                Rule::R_BRACE => { return Some(Token::RBrace) }
                Rule::L_BRACKT => { return Some(Token::LBrackt) }
                Rule::R_BRACKT => { return Some(Token::RBrackt) }
                Rule::COMMA => { return Some(Token::Comma) }
                Rule::SEMICOLON => { return Some(Token::Semicolon) }
                Rule::OCT_INTEGER => { return Some(Token::IntConst(i32::from_str_radix(inner.as_str().trim_start_matches("0"), 8).unwrap())) }
                Rule::HEX_INTEGER => { return Some(Token::IntConst(i32::from_str_radix(inner.as_str().trim_start_matches("0x"), 16).unwrap())) }
                Rule::DEX_INTEGER => { return Some(Token::IntConst(i32::from_str(inner.as_str()).unwrap())) }
                Rule::ZERO => { return Some(Token::IntConst(0)) }
                Rule::IDENT => { return Some(Token::Ident(inner.as_str().to_string())) }
                Rule::integer | Rule::token | Rule::keywords | Rule::file | Rule::operators | Rule::symbols => { return Self::get_token_name(inner) }
                _ => { return None; }
            }
        }

        None
    }
}

fn is_uppercase(str: &str) -> bool {
    str.chars().all(|c| c.is_uppercase() || c == '_' || c.is_numeric())
}